Allow loading of ELF kernel images that support both PAE and non-PAE.
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Thu, 14 Dec 2006 10:29:44 +0000 (10:29 +0000)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Thu, 14 Dec 2006 10:29:44 +0000 (10:29 +0000)
Also change the elf loader to not look for a strings section unless it
is needed.
Signed-off-by: Bruce Rogers <brogers@novell.com>
tools/libxc/xc_linux_build.c
tools/libxc/xc_load_elf.c
tools/libxc/xg_private.h
xen/arch/x86/domain_build.c
xen/common/elf.c
xen/include/xen/sched.h

index 7cbd03529bb6f3547cc96eeda218f53a90ecb5cf..1ce8107a32b3d2cd6bbe8d21ec835e83317976be 100644 (file)
@@ -596,15 +596,21 @@ static int compat_check(int xc_handle, struct domain_setup_info *dsi)
     }
 
     if (strstr(xen_caps, "xen-3.0-x86_32p")) {
-        if (dsi->pae_kernel == PAEKERN_no) {
+        if (dsi->pae_kernel == PAEKERN_bimodal) {
+            dsi->pae_kernel = PAEKERN_extended_cr3;
+        } else if (dsi->pae_kernel == PAEKERN_no) {
             xc_set_error(XC_INVALID_KERNEL,
                          "Non PAE-kernel on PAE host.");
             return 0;
         }
-    } else if (dsi->pae_kernel != PAEKERN_no) {
-        xc_set_error(XC_INVALID_KERNEL,
-                     "PAE-kernel on non-PAE host.");
-        return 0;
+    } else {
+        if (dsi->pae_kernel == PAEKERN_bimodal) {
+            dsi->pae_kernel = PAEKERN_no;
+        } else if (dsi->pae_kernel != PAEKERN_no) {
+            xc_set_error(XC_INVALID_KERNEL,
+                         "PAE-kernel on non-PAE host.");
+            return 0;
+        }
     }
 
     return 1;
index f8a28fb83c589bfcefcc2829a0b3410ec8deeb88..331165f62a65c965adcbcfe3d3b7ab791a0d0b2c 100644 (file)
@@ -325,17 +325,6 @@ static int parseelfimage(const char *image,
         return -EINVAL;
     }
 
-    /* Find the section-header strings table. */
-    if ( ehdr->e_shstrndx == SHN_UNDEF )
-    {
-        xc_set_error(XC_INVALID_KERNEL,
-                     "ELF image has no section-header strings table (shstrtab).");
-        return -EINVAL;
-    }
-    shdr = (Elf_Shdr *)(image + ehdr->e_shoff +
-                        (ehdr->e_shstrndx*ehdr->e_shentsize));
-    shstrtab = image + shdr->sh_offset;
-
     dsi->__elfnote_section = NULL;
     dsi->__xen_guest_string = NULL;
 
@@ -354,6 +343,17 @@ static int parseelfimage(const char *image,
     /* Fall back to looking for the special '__xen_guest' section. */
     if ( dsi->__elfnote_section == NULL )
     {
+        /* Find the section-header strings table. */
+        if ( ehdr->e_shstrndx == SHN_UNDEF )
+        {
+            xc_set_error(XC_INVALID_KERNEL,
+                         "ELF image has no section-header strings table.");
+            return -EINVAL;
+        }
+        shdr = (Elf_Shdr *)(image + ehdr->e_shoff +
+                            (ehdr->e_shstrndx*ehdr->e_shentsize));
+        shstrtab = image + shdr->sh_offset;
+
         for ( h = 0; h < ehdr->e_shnum; h++ )
         {
             shdr = (Elf_Shdr *)(image + ehdr->e_shoff + (h*ehdr->e_shentsize));
@@ -400,6 +400,8 @@ static int parseelfimage(const char *image,
     }
 
     /*
+     * A "bimodal" ELF note indicates the kernel will adjust to the
+     * current paging mode, including handling extended cr3 syntax.
      * If we have ELF notes then PAE=yes implies that we must support
      * the extended cr3 syntax. Otherwise we need to find the
      * [extended-cr3] syntax in the __xen_guest string.
@@ -408,7 +410,9 @@ static int parseelfimage(const char *image,
     if ( dsi->__elfnote_section )
     {
         p = xen_elfnote_string(dsi, XEN_ELFNOTE_PAE_MODE);
-        if ( p != NULL && strncmp(p, "yes", 3) == 0 )
+        if ( p != NULL && strncmp(p, "bimodal", 7) == 0 )
+            dsi->pae_kernel = PAEKERN_bimodal;
+        else if ( p != NULL && strncmp(p, "yes", 3) == 0 )
             dsi->pae_kernel = PAEKERN_extended_cr3;
 
     }
index 64ac8fad4878a2c4059656185865f5c5d8169bba..5533364f4af3e21ef6f1642910f05073e688baa1 100644 (file)
@@ -132,6 +132,7 @@ struct domain_setup_info
 #define PAEKERN_no           0
 #define PAEKERN_yes          1
 #define PAEKERN_extended_cr3 2
+#define PAEKERN_bimodal      3
     unsigned int  pae_kernel;
 
     unsigned int  load_symtab;
index bb597b2a50809d21e63fdce70167ae4d598c3da8..c092149def8450be808897b6f27bdb71b319af9c 100644 (file)
@@ -321,8 +321,11 @@ int construct_dom0(struct domain *d,
     if ( (rc = parseelfimage(&dsi)) != 0 )
         return rc;
 
-    dom0_pae = (dsi.pae_kernel != PAEKERN_no);
     xen_pae  = (CONFIG_PAGING_LEVELS == 3);
+    if (dsi.pae_kernel == PAEKERN_bimodal)
+        dom0_pae = xen_pae; 
+    else
+        dom0_pae = (dsi.pae_kernel != PAEKERN_no);
     if ( dom0_pae != xen_pae )
     {
         printk("PAE mode mismatch between Xen and DOM0 (xen=%s, dom0=%s)\n",
@@ -330,7 +333,8 @@ int construct_dom0(struct domain *d,
         return -EINVAL;
     }
 
-    if ( xen_pae && dsi.pae_kernel == PAEKERN_extended_cr3 )
+    if ( xen_pae && (dsi.pae_kernel == PAEKERN_extended_cr3 ||
+            dsi.pae_kernel == PAEKERN_bimodal) )
             set_bit(VMASST_TYPE_pae_extended_cr3, &d->vm_assist);
 
     if ( (p = xen_elfnote_string(&dsi, XEN_ELFNOTE_FEATURES)) != NULL )
index 83381b4b1a5fbe5948c4783ade8464ac17fccb0c..ab5a9ba8839b99338f5ac4eafdac889784ce36dc 100644 (file)
@@ -216,16 +216,6 @@ int parseelfimage(struct domain_setup_info *dsi)
         return -EINVAL;
     }
 
-    /* Find the section-header strings table. */
-    if ( ehdr->e_shstrndx == SHN_UNDEF )
-    {
-        printk("ELF image has no section-header strings table (shstrtab).\n");
-        return -EINVAL;
-    }
-    shdr = (Elf_Shdr *)(image + ehdr->e_shoff +
-                        (ehdr->e_shstrndx*ehdr->e_shentsize));
-    shstrtab = image + shdr->sh_offset;
-
     dsi->__elfnote_section = NULL;
     dsi->__xen_guest_string = NULL;
 
@@ -244,6 +234,16 @@ int parseelfimage(struct domain_setup_info *dsi)
     /* Fall back to looking for the special '__xen_guest' section. */
     if ( dsi->__elfnote_section == NULL )
     {
+        /* Find the section-header strings table. */
+        if ( ehdr->e_shstrndx == SHN_UNDEF )
+        {
+            printk("ELF image has no section-header strings table.\n");
+            return -EINVAL;
+        }
+        shdr = (Elf_Shdr *)(image + ehdr->e_shoff +
+                            (ehdr->e_shstrndx*ehdr->e_shentsize));
+        shstrtab = image + shdr->sh_offset;
+
         for ( h = 0; h < ehdr->e_shnum; h++ )
         {
             shdr = (Elf_Shdr *)(image + ehdr->e_shoff + (h*ehdr->e_shentsize));
@@ -286,6 +286,8 @@ int parseelfimage(struct domain_setup_info *dsi)
     }
 
     /*
+     * A "bimodal" ELF note indicates the kernel will adjust to the
+     * current paging mode, including handling extended cr3 syntax.
      * If we have ELF notes then PAE=yes implies that we must support
      * the extended cr3 syntax. Otherwise we need to find the
      * [extended-cr3] syntax in the __xen_guest string.
@@ -294,9 +296,10 @@ int parseelfimage(struct domain_setup_info *dsi)
     if ( dsi->__elfnote_section )
     {
         p = xen_elfnote_string(dsi, XEN_ELFNOTE_PAE_MODE);
-        if ( p != NULL && strncmp(p, "yes", 3) == 0 )
+        if ( p != NULL && strncmp(p, "bimodal", 7) == 0 )
+            dsi->pae_kernel = PAEKERN_bimodal;
+        else if ( p != NULL && strncmp(p, "yes", 3) == 0 )
             dsi->pae_kernel = PAEKERN_extended_cr3;
-
     }
     else
     {
index 01cc866154100297343f363656051449d7ccabbc..1aa4f59a3c613c1d731d8aeb9876f8056beb5b67 100644 (file)
@@ -188,6 +188,7 @@ struct domain_setup_info
 #define PAEKERN_no           0
 #define PAEKERN_yes          1
 #define PAEKERN_extended_cr3 2
+#define PAEKERN_bimodal      3
     unsigned int  pae_kernel;
     /* Initialised by loader: Private. */
     unsigned long elf_paddr_offset;